﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Slf;
using System.Reflection;

namespace Project.Under.Test
{
  [TestClass]
  public class CommunicationLogicTest
  {
    [TestMethod]
    public void SendMessage_RemoteServiceOK_MessageSent()
    {
      // create our test fixture
      StubbedRemoteService service = new StubbedRemoteService();
      CommunicationLogic comLogic = new CommunicationLogic(service);      

      // run the test
      string message = "Hello World!";
      comLogic.SendMessage(message);

      // verify that the given serivce was used to send the message
      Assert.AreEqual(message, service.SentMessage);
    }

    [TestMethod]
    public void SendMessage_RemoteServiceFails_FailureLogged()
    {
      // ensure that we record logged messages by supplying a test logger
      // because our class under creates a static logger, we have to 'inject' our
      // test logger.

      TestLogger logger = new TestLogger();
      typeof(CommunicationLogic).GetField("logger", BindingFlags.NonPublic | BindingFlags.Static)
                                .SetValue(null, logger);


      // create our test fixture
      StubbedRemoteService service = new StubbedRemoteService()
      {
        FailOnSend = true
      };
      CommunicationLogic comLogic = new CommunicationLogic(service);

      // run the test
      string message = "Hello World!";
      comLogic.SendMessage(message);

      // verify that the given serivce was used to send the message
      Assert.AreEqual(message, service.SentMessage);

      // verify that the exception was logged
      Assert.AreEqual(1, logger.LoggedItems.Count);
      Assert.AreEqual(LogLevel.Warn, logger.LoggedItems[0].LogLevel);
      Assert.IsNotNull(logger.LoggedItems[0].Exception);
    }

    /// <summary>
    /// A stub IRemoteService for test purposes
    /// </summary>
    private class StubbedRemoteService : IRemoteService
    {
      public bool FailOnSend = false;

      public string SentMessage = null;

      public void SendMessage(string message)
      {
        SentMessage = message;
        if (FailOnSend)
        {
          throw new Exception("Message send failed");
        }        
      }

    }
  }
}
